﻿using System;
using System.Buffers;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Text;
using System.Threading.Tasks;


namespace System.Net.Sockets.Kcp.Simple
{
    public interface IKcpClient
    {
        int Send(byte[] buffer,int length);
        void Receive(IMemoryOwner<byte> buffer,int length);
        void DispatchNetEvent();
    }
    /// <summary>
    /// 简单例子
    /// </summary>
    public abstract class SimpleKcpClient : IKcpCallback,IRentable,IKcpClient
    {
        UdpClient client;
        bool started;

        public virtual void Start()
        {
            started = true;
            BeginRecv();
            ReceiveKcpMsg();
        }

        public virtual void Stop()
        {
            started = false;
        }

        public abstract void Receive(IMemoryOwner<byte> buffer, int length);
        public abstract void DispatchNetEvent();
        public abstract IMemoryOwner<byte> RentBuffer(int length);

        public void Update()
        {
            DispatchNetEvent();
        }

        public SimpleKcpClient(int port)
            : this(port, null)
        {

        }

        public SimpleKcpClient(int port, IPEndPoint endPoint)
        {
            client = new UdpClient(port);
            kcp = new SimpleSegManager.Kcp(2001, this,this);
            this.EndPoint = endPoint;
        }

        public SimpleSegManager.Kcp kcp { get; }
        public IPEndPoint EndPoint { get; set; }

        public void Output(IMemoryOwner<byte> buffer, int avalidLength)
        {
            var s = buffer.Memory.Span.Slice(0, avalidLength).ToArray();
            client.SendAsync(s, s.Length, EndPoint);
            buffer.Dispose();
        }

        public int Send(byte[] datagram, int bytes)
        {
            return kcp.Send(datagram.AsSpan().Slice(0, bytes));
        }

        public async void ReceiveKcpMsg()
        {
            if (!started)
                return;

            var (buffer, avalidLength) = kcp.TryRecv();
            await Task.Delay(10);
            if(buffer != null)
            {
                Receive(buffer, avalidLength);
                buffer.Dispose();
            }
            ReceiveKcpMsg();
        }

        private async void BeginRecv()
        {
            if (!started)
                return;
            var res = await client.ReceiveAsync();
            EndPoint = res.RemoteEndPoint;
            kcp.Input(res.Buffer);
            BeginRecv();
        }
    }
}



